package gouroutine_pool

import (
	"sync/atomic"
	"time"
)

type runFunc func(in interface{}) (out interface{}, err error)

var id int64 = 0

// 任务实体
type Task struct {
	id         int64            // taskId
	state      int              // 任务状态
	resultChan chan interface{} // 任务结果
	mata       string           // 任务元信息
	timeFiled
	funcFiled
}

type defaultChannel chan interface{}

type timeFiled struct {
	startTime time.Time     // 任务开始时间
	endTime   time.Time     // 任务结束时间
	timeOut   int           // 任务超时时间
	timeUnit  time.Duration // 时间单位
}

type funcFiled struct {
	param    interface{} // 任务参数
	run      runFunc     // 执行此任务的函数
	callBack runFunc     // 任务执行失败时的回调方法
}

// 任务的执行
func (t *Task) Exec() {
	t.startTime = time.Now()
	t.state = RUNNING

	res, err := t.run(t.param)
	if err != nil {
		t.state = FAIL
	}

	// 任务完成
	t.resultChan <- res
	t.state = DONE
	t.endTime = time.Now()
}

// 新建一个任务
func NewTask(run runFunc, param interface{}, timeOut int, timeUnit time.Duration, callBack runFunc, mata string) *Task {
	t := new(Task)
	t.runFunc(run).
		callBackFunc(callBack).
		Args(param).
		TimeOut(timeOut).
		TimeUnit(timeUnit).
		Mata(mata).
		State(NEW)
	t.id = atomic.AddInt64(&id, 1)
	t.resultChan = make(defaultChannel, 1)
	return t
}

func (t *Task) isDone() bool {
	return t.state == DONE
}

func (t *Task) cancel() {
	t.state = CANCEL
}

// builder
func (t *Task) Mata(mata string) *Task {
	t.mata = mata
	return t
}

func (t *Task) TimeOut(timeOut int) *Task {
	t.timeOut = timeOut
	return t
}

func (t *Task) TimeUnit(timeUnit time.Duration) *Task {
	t.timeUnit = timeUnit
	return t
}

func (t *Task) Args(param interface{}) *Task {
	t.param = param
	return t
}

func (t *Task) State(s int) *Task {
	t.state = s
	return t
}

func (t *Task) runFunc(f runFunc) *Task {
	t.run = f
	return t
}

func (t *Task) callBackFunc(f runFunc) *Task {
	t.callBack = f
	return t
}
